<?php
    $start_time = microtime(true);
    /**
     * Визуализатор баз данных
     * @author Anton Fisher <aka.lenin@gmail.com>
     * @version 1.0.0 (12.2009)
     *
     * поддержка:
     *  - mysql (dump данные)
     */

    // ------------------------------------------------------------------------
    // --- обработка ---
    class odbv {
        private $font_size              = 8;
        private $field_size             = 0;
        private $table_width            = 120;
        private $table_distance         = 54;
        private $grid                   = 0;
        private $file                   = 'files/db_backup.txt';
        private $font_file              = 'lib/verdana.ttf';
        private $arr_tables             = array();
        private $arr_tables_positions   = array();
        private $arr_tables_sizes       = array();
        private $arr_tables_xy          = array();
        private $arr_links_xy           = array();
        private $arr_graf               = array();
        private $arr_graf_matr          = array();
        private $arr_links              = array();
        private $arr_note               = array();
        private $arr_colors             = array();

        private $image_width          = 0;
        private $image_height         = 0;

        // ------ colors ---

        function __construct() {
            $this->field_size = 2 + $this->font_size + 2;
            $this->grid = $this->field_size / 2;
            $this->arr_colors['font']           = array('0', '0', '0');
            $this->arr_colors['table_border']   = array('130', '130', '130');
            $this->arr_colors['background']     = array('255', '255', '255');
            $this->arr_colors['link']           = array('100', '100', '100');
//            $this->arr_colors['grid']           = array('150', '150', '150');
            $this->arr_colors['grid']           = array('220', '220', '220');
        }

        private function get_data() {
            $source = '';
            $arr_result = array();
            $arr_result['count_create'] = 0;
            $arr_result['count_alter']  = 0;
            $arr_result['count_other']  = 0;

            $fp = fopen($this->file, "r");
            while ($str = fgets($fp)) {
                $str_cut = str_replace("\r", '', str_replace("\n", '', $str));
                $str_cut = ereg_replace("--.*", '', $str_cut);
                if ($str_cut != '') {
                    $source .= $str_cut;
                }
            }

            $arr_source = explode(';', $source);
            foreach ($arr_source as $item) {
                $item = trim($item);
                //if (strpos($item, "CREATE TABLE") === 0) {
                //TODO исправить проблемы с кодировкой
                if (strpos($item, "CREATE TABLE") === 0 || strpos($item, "CREATE TABLE") === 3) {
                    $this->add_table($item);
                    $arr_result['count_create'] ++;
                } elseif (strpos($item, "ALTER TABLE ") === 0) {
                    $this->add_link($item);
                    $arr_result['count_alter'] ++;
                } else {
                    // $this->add_note($item);
                    $arr_result['count_other'] ++;
                }
            }

            return $arr_result;
        }

        private function add_table($table) {
            $arr_table = array();
            //echo $table.'<br />';
            
            $arr_tmp = false;
            preg_match("/`[A-z0-9_-]+`/", $table, $arr_tmp);
            if (isset($arr_tmp[0]) && $arr_tmp[0] != '') {
                $arr_table['title'] = str_replace('`', '', $arr_tmp[0]);
            } else {
                return false;
            }

            $arr_tmp = false;
            preg_match("/(\()(.+)(\))/", $table, $arr_tmp);
            if (isset($arr_tmp[2]) && $arr_tmp[2] != '') {
                $arr_fields = explode(',', $arr_tmp[2]);
                foreach ($arr_fields as $field) {
                    $arr_tmp = false;
                    if (strpos($field, 'KEY') === false) {
                        preg_match("/`[A-z0-9_-]+`/", $field, $arr_tmp);
                        if (isset($arr_tmp[0]) && $arr_tmp[0] != '' && strpos($arr_tmp, 'KEY') === false) {
                            $arr_table['fields'][]['title'] = str_replace('`', '', $arr_tmp[0]);
                        }
                    }
                }
            } else {
                return false;
            }

            $this->arr_tables[] = $arr_table;
            return true;
        }

        private function add_link($link) {
            $arr_links  = array();
            $arr_link   = array();

            //echo '<pre>';
            //echo $link.'<br />';

            $arr_tmp = false;
            preg_match("/(`)([A-z0-9_-]+)(`)(.+)/", $link, $arr_tmp);
            if (isset($arr_tmp[2]) && $arr_tmp[2] != '') {
                $arr_link['from_table'] = $arr_tmp[2];
                $link = explode('ADD CONSTRAINT', $arr_tmp[4]);
            } else {
                return false;
            }

            $arr_tmp = false;
            if (is_array($link)) {
                foreach ($link as $item) {
                    preg_match("/(FOREIGN KEY )(\(`)([A-z0-9_-]+)(`\))/", $item, $arr_tmp);
                    if (isset($arr_tmp[3]) && $arr_tmp[3] != '') {
                        $arr_link['from_field'] = $arr_tmp[3];
                        $arr_keys = $this->get_table_key($arr_link['from_table'], $arr_link['from_field']);
                        if ($arr_keys) {
                            $arr_link['from_table_key']     = $arr_keys['table_key'];
                            $arr_link['from_field_key']    = $arr_keys['field_key'];
                            preg_match("/(REFERENCES `)([A-z0-9_-]+)(` )(\(`)([A-z0-9_-]+)(`\))/", $item, $arr_tmp);
                            if (isset($arr_tmp[2]) && $arr_tmp[2] != '' && isset($arr_tmp[5]) && $arr_tmp[5] != '') {
                                $arr_keys = $this->get_table_key($arr_tmp[2], $arr_tmp[5]);
                                if ($arr_keys) {
                                    $arr_link['to_table']     = $arr_tmp[2];
                                    $arr_link['to_field']     = $arr_tmp[5];
                                    $arr_link['to_table_key'] = $arr_keys['table_key'];
                                    $arr_link['to_field_key'] = $arr_keys['field_key'];

                                    $arr_links[] = $arr_link;
                                }
                            }
                        } else {
                            return false;
                        }
                    }
                }
            } else {
                return false;
            }

            $this->arr_links = array_merge($this->arr_links, $arr_links);
            return true;
        }

        private function get_table_key($table_title, $field_title) {
            $arr_result = false;
            $flag_break = false;
            if ($table_title != '') {
                foreach ($this->arr_tables as $k => $table) {
                    if ($table['title'] == $table_title) {
                        foreach ($table['fields'] as $kk => $field) {
                            if ($field['title'] == $field_title) {
                                $arr_result = array('table_key' => $k, 'field_key' => $kk);
                                $flag_break = true;
                                break;
                            }
                        }
                    }
                    if ($flag_break) break;
                }
            }
            return $arr_result;
        }

        public function set_positions() {
            $count_all  = sizeof($this->arr_tables);
            $rows = 1;                                              // число предпологаемых строк
            $item_in_string = $count_all;                           // число предпологаемых элементов в столбце
            while (($item_in_string / $rows) > (4 / 3)) {           // ищем соотношение 4 / 3 (альбомный лист)
                $item_in_string --;
                $rows = (int) ($count_all / $item_in_string) + 1;
            }

            $arr_sizes = array();                                   // временный массив размеров таблиц
            $i = 0;
            foreach ($this->arr_tables as $k => $item) {
                $arr_sizes[$k] = sizeof($item['fields']);
            }

            arsort($arr_sizes);                                     // сортируем размеры по убыванию

            $this->arr_tables_positions = array();                  // массив позиций на экране (ключи)
            $this->arr_tables_sizes     = array();                  // временный массив с размером каждой таблицы
            $arr_sizes_keys[]           = array();                  // временный массив исходной сортировки таблиц

            $col = 0;                                               // рассматриваемый столбец
            $last_used_key = 0;                                     // последний проверенный ключ таблицы
            foreach ($arr_sizes as $k => $item) {
                $arr_sizes_keys[] =  array('key' => $k, 'size' => $item);
                if ($col < $item_in_string) {                       // записываем 1ую строку будущего массива позиций
                    $this->arr_tables_positions[$col][0]    = $k;
                    $this->arr_tables_sizes[$col][0]        = ($item + 1) * $this->field_size + $this->table_distance;
                    $last_used_key                          = $col;
                }
                $col ++;
            }

            // поочередно рассматриваем каждый столбец
            // в самый кородкий дописываем в конец следующую таблицу
            // и так далее, пока не будут записанны все таблицы
            $last_used_key ++;
            while ($last_used_key + 1 < sizeof($arr_sizes_keys)) {
                $min_col_summ = 10000;                              // минимальная сумма размеров таблиц в столбце
                $min_col = 0;                                       // столбец с минимальной суммой размеров таблиц
                $col = 0;                                           // рассматриваемый столбец
                while ($col < $item_in_string) {
                    $tmp_summ = array_sum($this->arr_tables_sizes[$col]);
                    if ($tmp_summ < $min_col_summ) {
                        $min_col_summ   = $tmp_summ;
                        $min_col        = $col;
                    }
                    $col ++;
                }
                $last_used_key ++;
                $this->arr_tables_positions[$min_col][] = $arr_sizes_keys[$last_used_key]['key'];
                $this->arr_tables_sizes[$min_col][]     = ($arr_sizes_keys[$last_used_key]['size'] + 1)
                    * $this->field_size + $this->table_distance;
            }
            
//            echo '<pre>';
//            print_r($arr_positions_keys);
//            echo '</pre>';
            return true;
        }


        public function draw_img() {
            $this->image_width = $this->table_distance
                + sizeof($this->arr_tables_positions) * ($this->table_width + $this->table_distance);

            $max_col_height = 1;
            foreach ($this->arr_tables_sizes as $col) {
                $col_height = array_sum($col);
                if ($col_height > $max_col_height) $max_col_height = $col_height;
            }
            $this->image_height = $this->table_distance + $max_col_height;

            //$image_width    = 990;
            //$image_height   = 900;

            $image = imagecreatetruecolor($this->image_width, $this->image_height);
            
            $c_back = imagecolorallocate(
                            $image,
                            $this->arr_colors['background'][0],
                            $this->arr_colors['background'][1],
                            $this->arr_colors['background'][2]
                        );

            //imagefilledrectangle($image, 0, 0, $image_width-1, $image_height-1, $c_back);
            imagefill($image, 0, 0, $c_back);
            
//            echo '<pre>';
//            print_r($this->arr_tables_positions);
//            echo '</pre>';

            foreach ($this->arr_tables_positions as $col => $items) {
                $y1 = $this->table_distance;
                foreach ($items as $row => $key_table) {
                    $table = $this->arr_tables[$key_table];

                    $x1 = $this->table_distance + (($this->table_width + $this->table_distance) * $col);
                    $x2 = $x1 + $this->table_width;
                    $y2 = $y1 + (sizeof($table['fields']) + 1) * $this->field_size;

                    $this->arr_tables_xy[$key_table] = array('x1' => $x1, 'y1' => $y1, 'x2' => $x2, 'y2' => $y2);
                    $y1 = $this->draw_table($image, $x1, $y1, $x2, $y2, $table);
                }
            }

            $this->draw_grids($image);
            $this->set_links_xy();
            //$this->draw_lineral_links($image);
            $this->draw_angle_links($image);
            
//            echo '<pre>';
//            print_r($this->arr_tables_xy);
//            echo '</pre>';

//            foreach ($this->arr_tables as $k => $table) {
//                $x1 = 10 + (100 * $k);
//                $x2 = $x1 + 90;
//                $y1 = 10;
//                $y2 = $y1 + (sizeof($table['fields']) + 1) * $this->field_size;
//
//                $this->draw_table($image, $x1, $y1, $x2, $y2, $table);
//            }

            imagepng($image, 'output/image.png');
            return true;
        }

        protected function draw_table ($image, $x1, $y1, $x2, $y2, $table) {
            $c_border = imagecolorallocate(
                                $image,
                                $this->arr_colors['table_border'][0],
                                $this->arr_colors['table_border'][1],
                                $this->arr_colors['table_border'][2]
                            );
            $c_black = imagecolorallocate(
                                $image,
                                $this->arr_colors['font'][0],
                                $this->arr_colors['font'][1],
                                $this->arr_colors['font'][2]
                            );
            
            imagerectangle($image, $x1, $y1, $x2, $y2, $c_border);
            imagerectangle($image, $x1-1, $y1-1, $x2+1, $y2+1, $c_border);
            imagerectangle($image, $x1, $y1, $x2, ($y1 + $this->field_size), $c_border);
            $y2_field = $y1 + $this->font_size + 2;
            
            $title = $table['title'];
            if (strlen($title) > 8) $title = substr($title, 0, 8).'..';

            imagettftext($image, $this->font_size, 0, ($x1 + 2), $y2_field, $c_black, $this->font_file,
                $title.' ('.sizeof($table['fields']).')');

            $y2_field += $this->field_size;
            foreach ($table['fields'] as $field) {
                $title = $field['title'];
                if (strlen($title) > 13) $title = substr($title, 0, 13).'..';
                imagettftext($image, $this->font_size, 0, ($x1 + 2), $y2_field, $c_black, $this->font_file, $title);
                $y2_field += $this->field_size;
            }

            $y2 += $this->table_distance;
            return $y2;
        }

        protected function set_links_xy() {
            if (sizeof($this->arr_links) > 0 && sizeof($this->arr_tables_xy) > 0) {
                foreach ($this->arr_links as $k => $link) {
                    $x1 = $this->arr_tables_xy[($link['from_table_key'])]['x1'];
                    $y1 = $this->arr_tables_xy[($link['from_table_key'])]['y1'];
                    $y1_field = $y1 + ($link['from_field_key'] + 1) * $this->field_size + $this->field_size / 2;
                    $x2 = $this->arr_tables_xy[($link['to_table_key'])]['x1'] + $this->table_width;
                    $y2 = $this->arr_tables_xy[($link['to_table_key'])]['y1']
                        + (($link['to_field_key'] + 1) * $this->field_size + $this->field_size / 2);

                    $this->arr_links_xy[$k] = array('id' => $link['to_table_key'].'_'.$link['to_field_key'],
                        'x1' => $x1, 'y1' => $y1_field, 'x2' => $x2, 'y2' => $y2);
                }
            }
        }

        protected function draw_lineral_links($image) {
            if (sizeof($this->arr_links_xy) > 0) {
                foreach ($this->arr_links_xy as $link) {
                    $c_rand = $this->get_rand_color($image);
                    imageline($image, $link['x1'], $link['y1'], $link['x2'], $link['y2'], $c_rand);
                }
            }
        }

        protected function draw_angle_links($image) {            
            $arr_connectors  = array();
            $arr_connector_on_point = array();

            //asort($this->arr_links_xy);
//            echo '<pre>';
//            print_r($this->arr_links_xy);exit;
            
            foreach ($this->arr_links_xy as $link) {
                $arr_connector  = array();

                $start_connector    = false;
                $end_connector      = false;
                foreach ($this->arr_graf as $k => $item) {
                    if ($item['x'] == $link['x1'] && $item['y'] == $link['y1']) {
                        $start_connector = $k;
                    }
                    if ($item['x'] == $link['x2'] && $item['y'] == $link['y2']) {
                        $end_connector = $k;
                    }
                }

                if ($start_connector === false || $end_connector === false) continue;

                // --- обход препятствий ---
                $arr_point_weght    = array();
                $arr_point_next     = array();
                $next_point         = -1;
                
                // прямой ход
                $i = $start_connector;
                $arr_point_weght[$i] = 1;
                $flag_stop = false;
                while (!$flag_stop) {
                    foreach ($this->arr_graf_matr[$i] as $k => $item) {
                        if(!isset($arr_point_weght[$k])) {
                            $arr_point_weght[$k] = $arr_point_weght[$i] + 1;
                            $arr_point_next[] = $k;
                            if ($k == $end_connector) $flag_stop = true;
                        }
                    }

                    $next_point ++;
                    if (!isset($arr_point_next[$next_point])) exit('no_next_point');
                    $i = $arr_point_next[$next_point];
                }

                // старые пути
                if (sizeof($arr_connector_on_point) > 0 && sizeof($arr_point_next) > 0) {
                    foreach ($arr_point_next as $item) {
                        if (isset($arr_connector_on_point[$item]) && $arr_connector_on_point[$item] != $link['id']) {
                            $arr_point_weght[$item] += 10;
                        }
                    }
                }

                // обратный ход
                $arr_we_was_here = array(); // вместо !in_array($k, $arr_connector)
                $i = $end_connector;
                $arr_connector[0] = $i;
                $ololo = 0;
                while ($i != $start_connector) {
                    //if ($ololo ++ > 500) break;
                    $next_point             = false;
                    $next_point_weight      = false;
                    $max_inc_point          = 0;
                    $max_inc_point_weight   = 0;
                    foreach ($this->arr_graf_matr[$i] as $k => $item) {
                        if (!isset($arr_we_was_here[$k]) && isset($arr_point_weght[$k])) {

                            if ($arr_point_weght[$k] < $arr_point_weght[$i]
                                //&& !in_array($k, $arr_connector)
                                //&& !isset($arr_we_was_here[$k])
                                && (!$next_point_weight || $next_point_weight > $arr_point_weght[$k])
                            ) {
                                $next_point = $k;
                                $next_point_weight = $arr_point_weght[$k];
                                //break;
                            }

                            if ($arr_point_weght[$k] > $max_inc_point_weight) {
                                $max_inc_point          = $k;
                                $max_inc_point_weight   = $arr_point_weght[$k];
                            }

                        }
                    }

                    if ($next_point === false) {
                        if ($max_inc_point > 0) {
                            $next_point = $max_inc_point;
                        } else {
                            break;
                            //exit('no_dec_next_point');
                        }
                    }

                    $arr_connector[] = $next_point;
                    $arr_we_was_here[$next_point] = true;
                    $arr_connector_on_point[$next_point] = $link['id'];
                    $i = $next_point;
                }
                
                $arr_connectors[] = array('id' => $link['id'], 'points' => $arr_connector);
            }

            // рисует коннекторы
            if (sizeof($arr_connectors) > 0) {
                $arr_connector_colors = array();
                
//                echo '<pre>'.$k.'!';
//                print_r($arr_connectors);
                foreach ($arr_connectors as $k => $connector) {
                    if (sizeof($connector['points']) > 0) {

                        if (!isset($arr_connector_colors[($arr_connectors[$k]['id'])])) {
                            $c_rand = $this->get_rand_color($image);
                            $arr_connector_colors[($arr_connectors[$k]['id'])] = $c_rand;
                        } else {
                            $c_rand = $arr_connector_colors[($arr_connectors[$k]['id'])];
                        }
                        
                        $last_x = false;
                        $last_y = false;
                        $last_k = false;
                        foreach ($connector['points'] as $k => $item) {
                                if ($last_x === false || $last_y === false) {
                                    $last_x = $this->arr_graf[$item]['x'];
                                    $last_y = $this->arr_graf[$item]['y'];
                                    $last_k = $k;
                                    continue;
                                }

                                $last_k = $k;

                                imageline($image,
                                    $last_x,
                                    $last_y,
                                    $this->arr_graf[$item]['x'],
                                    $this->arr_graf[$item]['y'],
                                    $c_rand);
                                imageline($image,
                                    $last_x+1,
                                    $last_y+1,
                                    $this->arr_graf[$item]['x']+1,
                                    $this->arr_graf[$item]['y']+1,
                                    $c_rand);

                                $last_x = $this->arr_graf[$item]['x'];
                                $last_y = $this->arr_graf[$item]['y'];
                        }
                    }
                }
            }

            // --- Дейкстра ---
//            $arr_close = array();
//            $arr_weight = array();
//            $arr_weight[($arr_connector[0])] = 0;
//            $i = $arr_connector[0];
//            $next = 0;
//            while ($i != $end_connector) {
//                if (!isset($this->arr_graf_matr[$i])) exit('bad $k..!'.$i);
//                foreach ($this->arr_graf_matr[$i] as $k => $item) {
//                    if (isset($arr_close[$i])) continue;
//                    $arr_next_k[] = $k;
//                    if (!isset($arr_weight[$k])) {
//                        $arr_weight[$k] = 1000000000;
//                    }
//                    if (($arr_weight[$i] + 1) < $arr_weight[$k]) {
//                        $arr_weight[$k] = $arr_weight[$i] + 1;
//                    }
//                }
//                $arr_close[$i] = true;
//                if (!isset($arr_next_k[$next])) break;
//                $i = $arr_next_k[$next];
//                $next++;
//            }
//
//
//            echo '<pre>';
//            print_r($arr_weight);
//            echo '</pre>';
//            echo '<pre>';
//            print_r($this->arr_graf_matr);
//            echo '</pre>';

            // рисует все связи в графе
//            $c_rand = $this->get_rand_color($image);
//            if (sizeof($this->arr_graf) > 0) {
//                foreach ($this->arr_graf_matr as $k => $item) {
//                    foreach ($item as $kk => $iitem) {
//                        imageline($image,
//                            $this->arr_graf[$k]['x'],
//                            $this->arr_graf[$k]['y'],
//                            $this->arr_graf[$kk]['x'],
//                            $this->arr_graf[$kk]['y'],
//                            $c_rand);
//                    }
//                }
//            }

            
//            foreach ($this->arr_graf as $k => $item) {
//
//            }
            return true;
        }

        protected function draw_grids($image) {
            $c_grid = imagecolorallocate(
                                $image,
                                $this->arr_colors['grid'][0],
                                $this->arr_colors['grid'][1],
                                $this->arr_colors['grid'][2]
                            );

            $this->arr_graf = '';
            for ($x = $this->grid; $x < $this->image_width; $x += $this->grid) {
                for ($y = $this->grid; $y < $this->image_height; $y += $this->grid) {
                    $flag_draw = true;
                    $need_connector = 2;
                    foreach ($this->arr_tables_xy as $table) {
                        if ($x > $table['x1'] && $x < $table['x2']
                            && $y >= $table['y1'] && $y <= $table['y2']
//                            ||
//                            ($y == $table['y1'] && $x == $table['x1'])
//                            ||
//                            ($y == $table['y2'] && $x == $table['x2'])
                        ) {
                            $flag_draw = false;
                            break;
                        }

                        if (($y == $table['y1'] && $x == $table['x1'])
                            || ($y == $table['y1'] && $x == $table['x2'])
                            || ($y == $table['y2'] && $x == $table['x1'])
                            || ($y == $table['y2'] && $x == $table['x2'])
                        ) {
                            $need_connector = 0;
                        } elseif (($x == $table['x1'] && $y <= $table['y2'] && $y >= $table['y1'])
                            || $x == $table['x2'] && $y <= $table['y2'] && $y >= $table['y1']
                        ) {
                            $need_connector = 1;
                        }
                    }
                    
                    if ($flag_draw) {
                        imagesetpixel($image, $x, $y, $c_grid);
                        $this->arr_graf[] = array('x' => $x, 'y' => $y, 'need_connector' => $need_connector);
                    }
                }
            }
            $this->set_graf_matr();
            return true;
        }

        protected function set_graf_matr() {
            //print_r($this->arr_graf[336]);
            foreach ($this->arr_graf as $k => $item) {
                //if ($k < 336 || $k > 859) continue;

                //$tmp_k = false;
                if (isset($this->arr_graf[$k + 1])
                    && abs($this->arr_graf[$k + 1]['y'] - $this->arr_graf[$k]['y']) == $this->grid
                    && $this->arr_graf[$k + 1]['x'] == $this->arr_graf[$k]['x']
                    && $this->arr_graf[$k + 1]['need_connector'] > 1
                    && $this->arr_graf[$k]['need_connector'] > 1
                ) {
                    //$tmp_k = $k;
                    $this->arr_graf_matr[$k][$k + 1] = true;
                    $this->arr_graf_matr[$k + 1][$k] = true;
                }

                $i = $k + 1;
//                $flag_added = false;
                while (isset($this->arr_graf[$i])) {
                    $tmp_sub = abs($this->arr_graf[$k]['x'] - $this->arr_graf[$i]['x']);
                    if ($tmp_sub == 0) {
                        $i++;
                        continue;
                    }

                    if ($tmp_sub > $this->grid) {
                        break;
                    }
                    
                    if ($tmp_sub == $this->grid
                        && $this->arr_graf[$k]['y'] == $this->arr_graf[$i]['y']
                        && $this->arr_graf[$i]['need_connector'] > 0
                        && $this->arr_graf[$k]['need_connector'] > 0
                    ) {
//                        $flag_added = true;
                        $this->arr_graf_matr[$k][$i] = true;
                        $this->arr_graf_matr[$i][$k] = true;
                        break;
                    }
                    $i++;
                }

//                if ($flag_added && $tmp_k !== false) {
//                    $this->arr_graf_matr[$tmp_k][$tmp_k + 1] = true;
//                    $this->arr_graf_matr[$tmp_k + 1][$tmp_k] = true;
//                }
            }
            
//            echo '<pre>';
//            print_r($this->arr_graf_matr);
//            echo '</pre>';
            return true;
        }

        protected function set_hierarchy() {
//            $arr_hierarchy  = array();
//            $arr_level      = array();
//            $arr_not_use    = array();
//            $level          = 0;
//            while (sizeof($arr_not_use) <= sizeof($this->arr_tables)) {
//                foreach ($this->arr_tables as $t => $table) {
//                    $flag_exist = false;
//                    foreach ($this->arr_links as $l => $link) {
//                        if ($link['from_table_key'] == $t && !array_search($l.'_'.$t, $arr_not_use)) {
//                            $flag_exist = true;
//                            break;
//                        }
//                    }
//                    if (!$flag_exist) {
//                        $arr_hierarchy[$level][] = $t;
//                        foreach ($this->arr_links as $l => $link) {
//                            foreach ($link['refer'] as $ll => $llink) {
//                               if ($llink['to_table_key'] == $t) {
//                                    $arr_not_use[] = $l.'_'.$t;
//                               }
//                            }
//                        }
//                    }
//                }
//                $level ++;
//            }
//
//            echo '<pre>';
//            print_r($arr_hierarchy);
//            echo '</pre>';

            return true;
        }
        
        protected function get_rand_color($image) {
            $arr_color = array('0', '0', '0');
            foreach ($arr_color as $k => $item) {
                $arr_color[$k] = rand(0,200);
            }
            return imagecolorallocate($image, $arr_color[0], $arr_color[1], $arr_color[2]);
        }

        public function make() {
            $this->get_data();
            $this->set_positions();
            $this->draw_img();
            
            $this->set_hierarchy();
            
//            echo '<pre>';
//            print_r($this->arr_graf);
//            echo '</pre>';

//            echo '<pre>';
//            print_r($this->arr_graf_matr);
//            echo '</pre>';

//            echo '<pre>';
//            print_r($this->arr_links);
//            echo '</pre>';

//            echo '<pre>';
//            print_r($this->arr_tables);
//            echo '</pre>';

            return true;
        }
    }

    // ------------------------------------------------------------------------
    // --- вывод ---
//    echo '  <html>
//                <thead>
//                    <title>Визуализация баз данных</title>
//                    <meta http-equiv="content-Type" content="text/html; charset=utf-8" />
//                    <meta name="author" content="Anton Fisher" />
//                    <style>
//                        #container      {font-size:11px; font-family:Tahoma; color:#666666;}
//                        #logo           {font-size:50px;}
//                    </style>
//                </thead>
//                <tbody>
//                    <div id="container">
//                        <div id="logo">
//                            Визуализация баз данных
//                        </div>
//                        <img src="image.png">';
//    $odbv = new odbv();
//    $odbv->make();
//
//    echo '<br />time: '.(microtime(true) - $start_time).' sec.<br />';
//    echo '          </div>
//                </tbody>
//            </html>';
?>